//! 管理部门
use std::{collections::HashMap, sync::Arc};

use ane_system::dao::{dept::DeptDo, DeptDetailVo};
use axum::{
    extract::{Path, Query},
    response::IntoResponse,
    routing::get,
    Extension, Router,
};
use validator::Validate;

use crate::{
    error::{AppError, AppResult},
    extract::{Json, ValJson},
    AppState,
};

pub fn get_route<S>() -> Router<S>
where
    S: Sync + Send + Clone + 'static,
{
    Router::<S>::new()
        .route("/", get(tree_table).post(create))
        .route("/:id", get(fetch_one).put(update).delete(delete))
}

#[inline]
pub async fn create(
    Extension(state): Extension<Arc<AppState>>,
    ValJson(data): ValJson<DeptDo>,
) -> AppResult<impl IntoResponse> {
    ane_system::dao::Dept::create(state.db(), data)
        .await
        .map(Json)
        .map_err(Into::into)
}

/// 获得id单位的详细信息[DeptDetailVo]
pub async fn fetch_one(
    Extension(state): Extension<Arc<AppState>>,
    Path(id): Path<i32>,
) -> AppResult<impl IntoResponse> {
    ane_system::dao::Dept::fetch_one::<DeptDetailVo>(state.db(), id, None, Some(false))
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn update(
    Extension(state): Extension<Arc<AppState>>,
    Path(id): Path<i32>,
    ValJson(mut data): ValJson<DeptDo>,
) -> AppResult<impl IntoResponse> {
    // 禁止修改根单位的status和parent_id
    if id == 1 {
        data.status = true;
        data.parent_id = Some(1);
    };
    ane_system::dao::Dept::update(state.db(), id, data)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn delete(
    Extension(state): Extension<Arc<AppState>>,
    Path(id): Path<i32>,
) -> AppResult<impl IntoResponse> {
    // 禁止删除根单位
    if id == 1 {
        return Err(AppError::Forbidden);
    };
    ane_system::dao::Dept::delete(state.db(), id)
        .await
        .map_err(Into::into)
        .map(|_| "Ok")
}

/// 获得单位的树结构
/// 使用query参数
/// - status 是否过滤 未启用的，true 表示过滤，默认false
/// - id 要获取的root id,默认为1，获取整个树
pub async fn tree_table(
    Extension(state): Extension<Arc<AppState>>,
    Query(query): Query<HashMap<String, String>>,
) -> AppResult<impl IntoResponse> {
    let status = query.get("status").map(|f| f == "true").unwrap_or(false);
    let id = query
        .get("id")
        .and_then(|f| f.parse::<i32>().ok())
        .unwrap_or(1);
    ane_system::dao::Dept::get_tree(state.db(), id, status)
        .await
        .map(Json)
        .map_err(Into::into)
}
